package com.tiantian.datajpa.dao.impl;

import java.io.Serializable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.persistence.EntityManager;
import javax.persistence.Query;

import org.hibernate.SQLQuery;
import org.springframework.data.jpa.repository.support.JpaEntityInformation;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;

import com.tiantian.datajpa.dao.BaseDAO;
import com.tiantian.datajpa.support.HumpResultTransformer;

/**
 * Copyright (c) 2015,重庆扬讯软件技术有限公司<br>
 * All rights reserved.<br>
 * 
 * 文件名称：BaseDaoImpl.java<br>
 * 摘要：基础DAO实现<br>
 * -------------------------------------------------------<br>
 * 当前版本：1.1.1<br>
 * 作者：吴炫<br>
 * 完成日期：2015年1月22日<br>
 * -------------------------------------------------------<br>
 * 取代版本：1.1.0<br>
 * 原作者：吴炫<br>
 * 完成日期：2015年1月22日<br>
 */
@SuppressWarnings("unchecked")
public class BaseDAOImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> implements BaseDAO<T, ID> {

	private EntityManager entityManager;

	public BaseDAOImpl(Class<T> domainClass, EntityManager em) {
		super(domainClass, em);
		this.entityManager = em;
	}

	public BaseDAOImpl(final JpaEntityInformation<T, ?> entityInformation, final EntityManager entityManager) {
		super(entityInformation, entityManager);
		this.entityManager = entityManager;
	}

	@Override
	public List<T> queryListBySql(String sql, int start, int length, Object[] params, Class<T> domainClass) {
		Query query = entityManager.createNativeQuery(sql, domainClass);
		setParameter(query, params);
		setPage(query, start, length);
		return (List<T>) query.getResultList();
	}

	@Override
	public List<T> queryListBySql(String sql, int start, int length, Map<String, Object> params, Class<T> domainClass) {
		Query query = entityManager.createNativeQuery(sql, domainClass);
		
		setParameter(query, params);
		setPage(query, start, length);
		return (List<T>) query.getResultList();
	}

	@Override
	public Long queryCountBySql(String sql, Object[] params) {
		Query query = entityManager.createNativeQuery(sql);
		setParameter(query, params);
		Object result = query.getSingleResult();
		if (result != null) {
			return Long.valueOf(result.toString());
		}
		return 0l;
	}

	@Override
	public Long queryCountBySql(String sql, Map<String, Object> params) {
		Query query = entityManager.createNativeQuery(sql);
		if (params != null) {
			setParameter(query, params);
		}
		Object result = query.getSingleResult();
		if (result != null) {
			return Long.valueOf(result.toString());
		}
		return 0l;
	}

	private void setParameter(Query query, Object[] params) {
		if (params != null) {
			int size = params.length;
			for (int i = 0; i < size; i++) {
				query.setParameter(i + 1, params[i]);
			}
		}
	}

	private void setParameter(Query query, Map<String, Object> params) {
		if (params != null) {
			Iterator<Map.Entry<String, Object>> it = params.entrySet().iterator();
			Entry<String, Object> en = null;
			while (it.hasNext()) {
				en = it.next();
				query.setParameter(en.getKey(), en.getValue());
			}
		}
	}

	private void setPage(Query query, int start, int length) {
		if (length > 0) {
			query.setFirstResult(start);
			query.setMaxResults(length);
		}
	}

	@Override
	public List<Map<String, Object>> queryListBySql(String sql, int start, int length, Map<String, Object> params) {
		Query query = entityManager.createNativeQuery(sql);
		if (params != null) {
			setParameter(query, params);
		}
		setPage(query, start, length);
		query.unwrap(SQLQuery.class).setResultTransformer(new HumpResultTransformer());
		return query.getResultList();
	}

	@Override
	public List<Map<String, Object>> queryListBySql(String sql, int start, int length, Object[] params) {
		Query query = entityManager.createNativeQuery(sql);
		setParameter(query, params);
		setPage(query, start, length);
		query.unwrap(SQLQuery.class).setResultTransformer(new HumpResultTransformer());
		return query.getResultList();
	}

	@Override
	public Boolean deleteByIds(Class<T> classOfT, String ids) {
		String tableName = classOfT.getAnnotation(javax.persistence.Table.class).name();
		String primaryKey = "";
		// Field fields[] = classOfT.getDeclaredFields();
		// for (Field field : fields) {
		// ExcelAnnotation ea =
		// field.getAnnotation(com.upsoft.ep.common.support.ExcelAnnotation.class);
		// ea.label();
		// Column col = field.getAnnotation(javax.persistence.Column.class);
		// Id id = field.getAnnotation(javax.persistence.Id.class);
		// if (id != null) {
		// primaryKey = col.name();
		// break;
		// }
		// }
		String sql = "delete " + tableName + " where " + primaryKey + " in ( " + warpSplitString(ids) + " ) ";
		int count = entityManager.createNativeQuery(sql).executeUpdate();
		if (count == 0)
			return false;
		return true;
	}

	/**
	 * 将字符串用逗号分割，并用单引号包裹
	 * 
	 * @date 2015年1月26日 下午2:32:35
	 * @author 蒋迪
	 * @param ids
	 * @return
	 */
	private String warpSplitString(String ids) {
		String result = "";
		String tmp[] = ids.split(",");
		for (String string : tmp) {
			result += "'" + string + "',";
		}
		result = result.substring(0, result.length() - 1);
		return result;
	}

	@Override
	public List<T> queryListBySql(String sql, Object[] params, Class<T> domainClass) {
		Query query = entityManager.createNativeQuery(sql, domainClass);
		setParameter(query, params);
		return (List<T>) query.getResultList();
	}

	@Override
	public List<T> queryListBySql(String sql, Map<String, Object> params, Class<T> domainClass) {
		Query query = entityManager.createNativeQuery(sql, domainClass);
		setParameter(query, params);
		return (List<T>) query.getResultList();
	}

	@Override
	public List<Map<String, Object>> queryListBySql(String sql, Map<String, Object> params) {
		Query query = entityManager.createNativeQuery(sql);
		if (params != null) {
			setParameter(query, params);
		}
		query.unwrap(SQLQuery.class).setResultTransformer(new HumpResultTransformer());
		return query.getResultList();
	}

	@Override
	public List<Map<String, Object>> queryListBySql(String sql, Object[] params) {
		Query query = entityManager.createNativeQuery(sql);
		if (params != null) {
			setParameter(query, params);
		}
		query.unwrap(SQLQuery.class).setResultTransformer(new HumpResultTransformer());
		return query.getResultList();
	}

	@Override
	public int executeSql(String sql, Map<String, Object> params) {
		Query query = entityManager.createNativeQuery(sql);
		if (params != null) {
			setParameter(query, params);
		}
		return query.executeUpdate();
	}

	@Override
	public int executeSql(String sql, Object[] params) {
		Query query = entityManager.createNativeQuery(sql);
		if (params != null) {
			setParameter(query, params);
		}
		return query.executeUpdate();
	}

	@Override
	public List<T> queryListByHql(String sql, int start, int length, Map<String, Object> params) {
		Query query = this.entityManager.createQuery(sql);
		if (params != null) {
			Entry<String, Object> en = null;
			Iterator<Map.Entry<String, Object>> it = params.entrySet().iterator();
			while (it.hasNext()) {
				en = it.next();
				query.setParameter(en.getKey().toString(), en.getValue());
			}
		}
		if (length > 0) {
			query.setFirstResult(start);
			query.setMaxResults(length);
		}
		return query.getResultList();
	}

	@Override
	public <U> List<U> queryListByHql(String sql, int start, int length, Map<String, Object> params, Class<U> domainClass) {
		Query query = this.entityManager.createQuery(sql, domainClass);
		if (params != null) {
			Entry<String, Object> en = null;
			Iterator<Map.Entry<String, Object>> it = params.entrySet().iterator();
			while (it.hasNext()) {
				en = it.next();
				query.setParameter(en.getKey().toString(), en.getValue());
			}
		}
		if (length > 0) {
			query.setFirstResult(start);
			query.setMaxResults(length);
		}
		return query.getResultList();
	}

	@Override
	public Long queryCountByHql(String sql, Map<String, Object> params) {
		Query query = this.entityManager.createQuery(sql);
		if (params != null) {

			Iterator<Map.Entry<String, Object>> it = params.entrySet().iterator();
			Entry<String, Object> en = null;
			while (it.hasNext()) {
				en = it.next();
				query.setParameter(en.getKey().toString(), en.getValue());
			}
		}
		Object result = query.getSingleResult();
		if (result != null) {
			return Long.valueOf(result.toString());
		}
		return 0L;
	}

	@Override
	public List<Map<String, Object>> queryHumpListMapBySql(String sql, Map<String, Object> params) {
		Query query = entityManager.createNativeQuery(sql);
		if (params != null) {
			setParameter(query, params);
		}
		query.unwrap(SQLQuery.class).setResultTransformer(new HumpResultTransformer());
		return query.getResultList();
	}

	@Override
	public List<Map<String, Object>> queryHumpListMapBySql(String sql, int start, int length, Map<String, Object> params) {
		Query query = entityManager.createNativeQuery(sql);
		if (params != null) {
			setParameter(query, params);
		}
		setPage(query, start, length);
		query.unwrap(SQLQuery.class).setResultTransformer(new HumpResultTransformer());
		return query.getResultList();
	}

}